<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>深拷贝</title>
</head>

<body>
    <script>
        const numberTag = '[object Number]';
        const stringTag = '[object String]';
        const symbolTag = '[object Symbol]';
        const boolTag = '[object Boolean]';
        const arrayTag = '[object Array]';
        const objectTag = '[object Object]';
        const mapTag = '[object Map]';
        const setTag = '[object Set]';
        const dateTag = '[object Date]';
        const errorTag = '[object Error]';
        const regexpTag = '[object RegExp]';
        const deepTag = [
            numberTag, stringTag, symbolTag, boolTag, arrayTag, objectTag, mapTag,
            setTag, dateTag, errorTag, regexpTag]

        function getType(target) {
            return Object.prototype.toString.call(target);
        }

        function isObject(target) {
            const type = typeof target;
            return target !== null && (type === 'object' || type === 'function');
        }
        function getInit(target) {
            const Ctor = target.constructor;
            return new Ctor();
        }
        //乞丐版深拷贝
        //  function deepClone(target){
        //     if(typeof target === 'object'){
        //         let res = {}
        //         for(const key in target){
        //             res[key] = deepClone(target[key])
        //         }
        //         return res
        //     }else{
        //         return target
        //     }
        // }

        // 考虑数组
        // function deepClone(target){
        //     if(typeof target === 'object'){
        //         let res = Array.isArray(target)? []:{}
        //         for(const key in target){
        //             res[key] = deepClone(target[key])
        //         }
        //         return res
        //     }else{
        //         return target
        //     }
        // }

        // 考虑循环引用
        // function deepClone(target, map = new Map()) {
        //     if (typeof target === 'object') {
        //         let res = Array.isArray(target) ? [] : {}
        //         if (map.get(target)) {
        //             return map.get(target)
        //         }
        //         map.set(target, res)
        //         for (const key in target) {
        //             res[key] = deepClone(target[key], map)
        //         }
        //         return res
        //     } else {
        //         return target
        //     }
        // }
        //考虑引用类型数据
        function clone(target, map = new Map()) {
            //克隆原始类型
            if (!isObject(target)) {
                return target
            }
            //初始化
            const type = getType(target)
            let res
            if (deepTag.includes(type)) {
                res = getInit(target, type)
            }
            //防止循环引用
            if (map.get(target)) {
                return map.get(target)
            }
            map.set(target, res)

            //克隆set
            if (type === setTag) {
                target.forEach(value => {
                    res.add(clone(value, map))
                })
                return res
            }
            //克隆map
            if (type === mapTag) {
                target.forEach((value, key) => {
                    res.set(key, clone(value, map))
                })
                return res
            }
            //克隆对象和数组
            const keys = type === arrayTag ? undefined : Object.keys(target)
            for (const key in keys) {

            }
        }
        const target = {
            field1: 1,
            field2: undefined,
            field3: {
                child: 'child'
            },
            field4: [2, 4, 8]
        }
        target.target = target
        const res = deepClone(target)
        console.log(target);
        console.log(res);
    </script>
</body>

</html>